using System.Text;

namespace KnowledgeQA.Core.Utils
{
    /// <summary>
    /// 编码处理工具类
    /// </summary>
    public static class EncodingUtils
    {
        /// <summary>
        /// 常见的中文编码列表
        /// </summary>
        private static readonly string[] ChineseEncodings = { "GBK", "GB2312", "GB18030", "Big5" };

        /// <summary>
        /// 检测文件编码
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>检测到的编码</returns>
        public static async Task<Encoding> DetectFileEncodingAsync(string filePath)
        {
            try
            {
                // 读取文件的前几个字节来检测编码
                var buffer = new byte[4096];
                using (var stream = File.OpenRead(filePath))
                {
                    await stream.ReadAsync(buffer, 0, buffer.Length);
                }

                return DetectEncodingFromBytes(buffer);
            }
            catch
            {
                // 回退到UTF-8
                return Encoding.UTF8;
            }
        }

        /// <summary>
        /// 从字节数组检测编码
        /// </summary>
        /// <param name="buffer">字节数组</param>
        /// <returns>检测到的编码</returns>
        public static Encoding DetectEncodingFromBytes(byte[] buffer)
        {
            // 检查BOM（字节顺序标记）
            if (buffer.Length >= 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF)
            {
                return Encoding.UTF8;
            }
            if (buffer.Length >= 2 && buffer[0] == 0xFF && buffer[1] == 0xFE)
            {
                return Encoding.Unicode;
            }
            if (buffer.Length >= 2 && buffer[0] == 0xFE && buffer[1] == 0xFF)
            {
                return Encoding.BigEndianUnicode;
            }
            if (buffer.Length >= 4 && buffer[0] == 0xFF && buffer[1] == 0xFE && buffer[2] == 0x00 && buffer[3] == 0x00)
            {
                return Encoding.UTF32;
            }

            // 检查是否为中文编码
            if (IsLikelyChineseEncoding(buffer))
            {
                foreach (var encodingName in ChineseEncodings)
                {
                    try
                    {
                        var encoding = Encoding.GetEncoding(encodingName);
                        if (IsValidEncoding(buffer, encoding))
                        {
                            return encoding;
                        }
                    }
                    catch
                    {
                        // 继续尝试下一个编码
                    }
                }
            }

            // 默认使用UTF-8
            return Encoding.UTF8;
        }

        /// <summary>
        /// 检查是否可能是中文编码
        /// </summary>
        /// <param name="buffer">字节数组</param>
        /// <returns>是否可能是中文编码</returns>
        private static bool IsLikelyChineseEncoding(byte[] buffer)
        {
            // 检查是否有连续的中文字符
            for (int i = 0; i < buffer.Length - 1; i++)
            {
                if (buffer[i] >= 0x81 && buffer[i] <= 0xFE && 
                    buffer[i + 1] >= 0x40 && buffer[i + 1] <= 0xFE)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 验证编码是否有效
        /// </summary>
        /// <param name="buffer">字节数组</param>
        /// <param name="encoding">编码</param>
        /// <returns>编码是否有效</returns>
        private static bool IsValidEncoding(byte[] buffer, Encoding encoding)
        {
            try
            {
                var decoded = encoding.GetString(buffer);
                // 检查解码后的字符串是否包含有效的中文字符
                return decoded.Any(c => c >= 0x4E00 && c <= 0x9FFF);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 清理文本内容
        /// </summary>
        /// <param name="content">原始内容</param>
        /// <returns>清理后的内容</returns>
        public static string CleanTextContent(string content)
        {
            if (string.IsNullOrEmpty(content))
                return string.Empty;

            // 移除控制字符（除了换行符、制表符、回车符）
            var cleanedChars = new List<char>();
            foreach (char c in content)
            {
                if (IsValidCharacter(c))
                {
                    cleanedChars.Add(c);
                }
            }

            var cleanedContent = new string(cleanedChars.ToArray());

            // 标准化换行符
            cleanedContent = cleanedContent.Replace("\r\n", "\n").Replace("\r", "\n");

            // 移除多余的空白字符
            cleanedContent = NormalizeWhitespace(cleanedContent);

            return cleanedContent;
        }

        /// <summary>
        /// 检查字符是否有效
        /// </summary>
        /// <param name="c">字符</param>
        /// <returns>是否有效</returns>
        private static bool IsValidCharacter(char c)
        {
            return c == '\n' || c == '\t' || c == '\r' || 
                   (c >= 32 && c <= 0xFFFF) || 
                   char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsSymbol(c) || char.IsWhiteSpace(c);
        }

        /// <summary>
        /// 标准化空白字符
        /// </summary>
        /// <param name="content">内容</param>
        /// <returns>标准化后的内容</returns>
        private static string NormalizeWhitespace(string content)
        {
            // 移除行首行尾空白
            var lines = content.Split('\n');
            var normalizedLines = new List<string>();

            foreach (var line in lines)
            {
                var trimmedLine = line.Trim();
                if (!string.IsNullOrEmpty(trimmedLine))
                {
                    normalizedLines.Add(trimmedLine);
                }
            }

            return string.Join("\n", normalizedLines);
        }

        /// <summary>
        /// 验证文本内容是否有效
        /// </summary>
        /// <param name="content">内容</param>
        /// <returns>是否有效</returns>
        public static bool IsValidTextContent(string? content)
        {
            if (string.IsNullOrEmpty(content))
                return false;

            // 检查内容长度
            if (content.Length < 10)
                return false;

            // 检查是否包含有效字符
            var validCharCount = content.Count(c => char.IsLetterOrDigit(c) || char.IsPunctuation(c));
            if (validCharCount < 5)
                return false;

            // 检查乱码字符比例
            var invalidCharCount = content.Count(c => !IsValidCharacter(c));
            var invalidRatio = (double)invalidCharCount / content.Length;
            
            if (invalidRatio > 0.1) // 超过10%的无效字符
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 获取文本内容的统计信息
        /// </summary>
        /// <param name="content">内容</param>
        /// <returns>统计信息</returns>
        public static TextContentStats GetTextContentStats(string content)
        {
            if (string.IsNullOrEmpty(content))
                return new TextContentStats();

            var stats = new TextContentStats
            {
                TotalLength = content.Length,
                ValidCharCount = content.Count(c => IsValidCharacter(c)),
                InvalidCharCount = content.Count(c => !IsValidCharacter(c)),
                LetterCount = content.Count(char.IsLetter),
                DigitCount = content.Count(char.IsDigit),
                PunctuationCount = content.Count(char.IsPunctuation),
                ChineseCharCount = content.Count(c => c >= 0x4E00 && c <= 0x9FFF),
                LineCount = content.Split('\n').Length
            };

            stats.InvalidRatio = (double)stats.InvalidCharCount / stats.TotalLength;
            stats.IsValid = stats.InvalidRatio <= 0.1 && stats.ValidCharCount >= 5;

            return stats;
        }
    }

    /// <summary>
    /// 文本内容统计信息
    /// </summary>
    public class TextContentStats
    {
        public int TotalLength { get; set; }
        public int ValidCharCount { get; set; }
        public int InvalidCharCount { get; set; }
        public int LetterCount { get; set; }
        public int DigitCount { get; set; }
        public int PunctuationCount { get; set; }
        public int ChineseCharCount { get; set; }
        public int LineCount { get; set; }
        public double InvalidRatio { get; set; }
        public bool IsValid { get; set; }
    }
} 